package com.ts.animal.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.ts.animal.constant.AnimalConstant;
import com.ts.animal.dao.ExInputsDao;
import com.ts.animal.dao.ExInputsSetDao;
import com.ts.animal.dao.InputsDao;
import com.ts.animal.domain.ExcelInputsDO;
import com.ts.animal.domain.InputsDO;
import com.ts.animal.domain.InputsSetDO;
import com.ts.animal.service.InputsService;
import com.ts.common.utils.DataPerUitl;
import com.ts.common.utils.Result;
import com.ts.common.utils.ShiroUtils;
import com.ts.common.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Transactional
@Service
public class InputsServiceImpl implements InputsService {
    @Autowired
    private InputsDao inputsDao;
    @Autowired
    private ExInputsDao exInputsDao;
    @Autowired
    private ExInputsSetDao exInputsSetDao;

    @Override
    public InputsDO get(Integer id) {
        return inputsDao.get(id);
    }

    @Override
    public List<InputsDO> list(Map<String, Object> map) {
        return inputsDao.list(map);
    }

    @Override
    public List<Map<String, Object>> exList(Map<String, Object> map) {
        map.putAll(DataPerUitl.deptPer("bs_inputs.dept_id"));
        return exInputsDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        map.putAll(DataPerUitl.deptPer("bs_inputs.dept_id"));
        return exInputsDao.count(map);
    }

    @Override
    public int exCount(Map<String, Object> map) {
        return exInputsDao.count(map);
    }

    @Override
    public int save(Result result, InputsDO inputs) {
        int ret = 0;

        if (!StringUtils.isEmpty(inputs.getParentNum())) {
            if (inputs.getParentNum().equals(inputs.getNum())) {
                result.set(Result.FAIL, "请输入正确的上一代编号", null);
                return ret;
            }
            Map<String, Object> map = Maps.newHashMap();
            map.put("num", inputs.getParentNum());
            List<InputsDO> parents = this.list(map);
            if (parents.size() > 0) {
                inputs.setParentId(parents.get(0).getId());
            } else {
                result.set(Result.FAIL, "请输入正确的上一代编号", null);
                return ret;
            }
        }

        if (StringUtils.isEmpty(inputs.getTypeName())) {
            result.set(Result.FAIL, "请选择动物类型", null);
            return ret;
        }

        Map<String, Object> map = Maps.newHashMap();
        map.put("num", inputs.getNum());
        if (inputsDao.list(map).size() > 0) {
            result.set(Result.FAIL, "已经存在动物编号【" + inputs.getNum() + "】", null);
            return ret;
        }
        inputs.setCreateUser((int) ShiroUtils.getUserId().longValue());
        if (inputs.getDeptId() == null) {
            inputs.setDeptId((int) ShiroUtils.getUser().getDeptId().longValue());
        }
        inputs.setCurWeight(inputs.getInitWeight());
        inputs.setCreateTime(new Date());
        inputs.setUpdateTime(new Date());
        inputs.setStatus(AnimalConstant.INPUTS_STATUS_FEEDING);
        ret = inputsDao.save(inputs);
        if (ret == 0) {
            result.set(Result.FAIL, "操作失败", null);
        }
        return ret;
    }

    @Override
    public int update(Result result, InputsDO inputs) {
        int ret = 0;
        if (inputs.getDeptId() == null) {
            inputs.setDeptId((int) ShiroUtils.getUser().getDeptId().longValue());
        }
        inputs.setUpdateUser((int) ShiroUtils.getUserId().longValue());
        inputs.setUpdateTime(new Date());

        if (!StringUtils.isEmpty(inputs.getParentNum())) {
            if (inputs.getParentNum().equals(inputs.getNum())) {
                result.set(Result.FAIL, "请输入正确的上一代编号", null);
                return ret;
            }
            Map<String, Object> map = Maps.newHashMap();
            map.put("num", inputs.getParentNum());
            List<InputsDO> parents = this.list(map);
            if (parents.size() > 0) {
                inputs.setParentId(parents.get(0).getId());
            } else {
                result.set(Result.FAIL, "请输入正确的上一代编号", null);
                return ret;
            }
        } else {
            inputs.setParentId(-1);
        }

        return inputsDao.update(inputs);
    }

    @Override
    public int update(InputsDO inputs) {
        return inputsDao.update(inputs);
    }

    @Override
    public int remove(Integer id) {
        return inputsDao.remove(id);
    }

    @Override
    public int batchRemove(Integer[] ids) {
        return inputsDao.batchRemove(ids);
    }

    @Override
    public InputsSetDO getInputSetDo(Integer deptId) {
        InputsSetDO inputsSetDO = exInputsSetDao.get(deptId);
        if (inputsSetDO == null) {
            inputsSetDO = new InputsSetDO();
            inputsSetDO.setDeptId(deptId);
        }
        return inputsSetDO;
    }

    @Override
    public void updateInputSetDo(InputsSetDO inputsSetDO) {
        exInputsSetDao.save(inputsSetDO);
    }

    @Override
    public Result upload(MultipartFile file) throws IOException {
        Result result = Result.ok();
        EasyExcel.read(file.getInputStream(), ExcelInputsDO.class, new ReadListener<ExcelInputsDO>() {
            Result result;
            ExInputsSetDao exInputsSetDao;
            /**
             * 单次缓存的数据量
             */
            public static final int BATCH_COUNT = 500;

            int updateRow = 0;
            /**
             *临时存储
             */
            private List<InputsDO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

            @Override
            public void invoke(ExcelInputsDO data, AnalysisContext context) {
                InputsDO inputsDO = new InputsDO();
                BeanUtils.copyProperties(data, inputsDO);
                cachedDataList.add(inputsDO);
                if (cachedDataList.size() >= BATCH_COUNT) {
                    saveData();
                    // 存储完成清理 list
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                saveData();
                result.setMsg("成功更新" + updateRow + "条记录");
            }

            /**
             * 加上存储数据库
             */
            private void saveData() {
                updateRow = +exInputsDao.batchUpdateInputsNum(cachedDataList);
                System.out.println("打印上传内容：" + JSON.toJSONString(cachedDataList));
            }

            public ReadListener accept(Result result, ExInputsSetDao exInputsSetDao) {
                this.result = result;
                this.exInputsSetDao = exInputsSetDao;
                return this;
            }
        }.accept(result, exInputsSetDao)).sheet().doRead();
        return result;
    }
}
